﻿// F. Unique Occurrences.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
https://codeforces.com/problemset/problem/1681/F

给你一棵由 n 个顶点组成的树。每条边上都写有一个整数值。
设 f(v,u) 是顶点 v 和 u 之间简单路径的边上精确出现一次的值的个数。
计算所有 1≤v<u≤n 的顶点 v 和 u 的总和 f(v,u)。

输入
第一行包含一个整数 n（2≤n≤5⋅105）--树中的顶点数。
接下来的 n-1 行分别包含三个整数 v、u 和 x（1≤v,u,x≤n）--一条边的描述：连接的顶点和写在上面的值。

给定的边构成一棵树。

输出
打印一个整数--所有 v<u 的顶点 v 和 u 的总和 f(v,u)。

Examples
InputCopy
3
1 2 1
1 3 2
OutputCopy
4
InputCopy
3
1 2 2
1 3 2
OutputCopy
2
InputCopy
5
1 4 4
1 2 3
3 4 4
4 5 5
OutputCopy
14
InputCopy
2
2 1 1
OutputCopy
1
InputCopy
10
10 2 3
3 8 8
4 8 9
5 8 5
3 10 7
7 8 2
5 6 6
9 3 4
1 6 3
OutputCopy
120
*/


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

using ll = long long;

const int N = 500010;

ll pre[N], sz[N], n;
ll ans;

pair<int, int> stk[N];
int top;

struct Edge {
	int x, y;
};

vector<Edge> g[N];

int root(int x) {
	return pre[x] == x ? x : root(pre[x]);
}

void init() {
	for (int i = 1; i <= n; i++) { pre[i] = i, sz[i] = 1; }
}

void merge(int x, int y) {
	int rx = root(x), ry = root(y);
	if (rx == ry) {
		stk[++top] = { -1,-1 };
		return;
	}
	if (sz[rx] > sz[ry]) swap(rx, ry);

	stk[++top] = { rx,ry };

	pre[rx] = ry;
	sz[ry] += sz[rx];
}


void undo() {
	if (!top) return;
	//auto [x, y] = stk[top--];
	int x = stk[top].first;
	int y = stk[top].second;
	top--;
	if (x == -1) return;
	pre[x] = x, sz[y] -= sz[x];
}

void AddNode(int w) {
	for (const auto& e : g[w]) {
		int x = e.x;
		int y = e.y;
		merge(x, y);
	}
}

void DelNode(int w) {
	for (int i = 1; i <= g[w].size(); ++i) undo();
}

void AddTree(int x) {
	if (x > n) return;
	AddNode(x);
	AddTree(x << 1), AddTree(x << 1 | 1);
}

void DelTree(int x) {
	if (x > n) return;
	DelNode(x);
	DelTree(x << 1); DelTree(x << 1| 1);
}

ll f(int w) {
	ll res = 0;
	for (const auto e : g[w]) {
		int x = e.x;
		int y = e.y;
		res += sz[root(x)] * sz[root(y)];
	}
	return res;
}


void dfs(int x) {
	if (x > n)return;
	AddNode(x);
	AddTree(x << 1 | 1);
	dfs(x << 1);
	DelTree(x << 1 | 1);

	AddTree(x << 1);
	dfs(x << 1 | 1);
	DelTree(x << 1);

	DelNode(x);

	AddTree(x << 1), AddTree(x << 1 | 1);
	ans += f(x);
	DelTree(x << 1), DelTree(x << 1 | 1);
}

void solve() {
	cin >> n;
	for (int i = 1; i < n; i++) {
		ll x, y, w; cin >> x >> y >> w;
		struct Edge e = { x,y };
		g[w].push_back(e);
	}
	init();
	dfs(1);
	cout << ans << endl;

}

int main()
{
	int T; T = 1;
	while (T--) {
		solve();
	}

	return 0;
}
 